package com.wocai.jrt.orgadmin.orders.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.inject.Inject;
import javax.inject.Named;

import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import com.vteba.common.exception.ServiceException;
import com.vteba.service.generic.impl.MyBatisServiceImpl;
import com.vteba.tx.jdbc.mybatis.spi.BaseDao;
import com.vteba.utils.common.BigDecimalUtils;
import com.vteba.utils.id.Ids;
import com.vteba.utils.id.ObjectId;
import com.vteba.web.action.JsonBean;
import com.wocai.jrt.orgadmin.employee.model.Employee;
import com.wocai.jrt.orgadmin.employee.model.EmployeeCommissionHistory;
import com.wocai.jrt.orgadmin.employee.model.EmployeeGroup;
import com.wocai.jrt.orgadmin.employee.model.GroupMember;
import com.wocai.jrt.orgadmin.employee.service.spi.EmployeeCommissionHistoryService;
import com.wocai.jrt.orgadmin.employee.service.spi.EmployeeGroupService;
import com.wocai.jrt.orgadmin.employee.service.spi.EmployeeService;
import com.wocai.jrt.orgadmin.employee.service.spi.GroupMemberService;
import com.wocai.jrt.orgadmin.investor.bean.EmpBreifBean;
import com.wocai.jrt.orgadmin.investor.bean.MatchReqBean;
import com.wocai.jrt.orgadmin.investor.model.Investor;
import com.wocai.jrt.orgadmin.investor.service.spi.InvestorService;
import com.wocai.jrt.orgadmin.issuers.bean.IssuersOrdersResBean;
import com.wocai.jrt.orgadmin.issuers.model.IssuersBack;
import com.wocai.jrt.orgadmin.issuers.service.spi.IssuersBackService;
import com.wocai.jrt.orgadmin.orders.bean.OfflineApplyResBean;
import com.wocai.jrt.orgadmin.orders.bean.OfflineOrderReqBean;
import com.wocai.jrt.orgadmin.orders.bean.OrderDetailResBean;
import com.wocai.jrt.orgadmin.orders.bean.OrderOfflineApplyResBean;
import com.wocai.jrt.orgadmin.orders.bean.OrderPaySerialResBean;
import com.wocai.jrt.orgadmin.orders.bean.OrderReqBean;
import com.wocai.jrt.orgadmin.orders.bean.OrderResBean;
import com.wocai.jrt.orgadmin.orders.bean.OrderStateResBean;
import com.wocai.jrt.orgadmin.orders.bean.OrderVisitResBean;
import com.wocai.jrt.orgadmin.orders.bean.ProductBreifBean;
import com.wocai.jrt.orgadmin.orders.dao.OrdersDao;
import com.wocai.jrt.orgadmin.orders.model.Orders;
import com.wocai.jrt.orgadmin.orders.model.OrdersBean;
import com.wocai.jrt.orgadmin.orders.service.spi.OrdersService;
import com.wocai.jrt.orgadmin.pay.model.PaySerial;
import com.wocai.jrt.orgadmin.pay.service.spi.PaySerialService;
import com.wocai.jrt.orgadmin.product.bean.ProductMatchReqBean;
import com.wocai.jrt.orgadmin.product.bean.ProductReqBean;
import com.wocai.jrt.orgadmin.product.model.Product;
import com.wocai.jrt.orgadmin.product.model.ProductGrade;
import com.wocai.jrt.orgadmin.product.service.spi.ProductGradeService;
import com.wocai.jrt.orgadmin.product.service.spi.ProductService;
import com.wocai.jrt.orgadmin.stats.bean.GroupOdersReqBean;
import com.wocai.jrt.orgadmin.stats.bean.IndexStatsReqBean;
import com.wocai.jrt.orgadmin.stats.bean.ProductEmpStatsReqBean;
import com.wocai.jrt.orgadmin.stats.bean.ProductEmpStatsResBean;
import com.wocai.jrt.orgadmin.stats.bean.ProductRecruitProgressEleBean;
import com.wocai.jrt.orgadmin.utils.ImgType;
import com.wocai.jrt.orgadmin.utils.MyFileUtils;
import com.wocai.jrt.orgadmin.utils.UserUtils;

/**
 * 订单相关的service业务实现。
 * 
 * @author yinlei
 * @date 2015-8-4 19:44:34
 */
@Named
public class OrdersServiceImpl extends MyBatisServiceImpl<Orders, OrdersBean, String> implements
		OrdersService {
	private static final Logger LOGGER = LoggerFactory.getLogger(OrdersServiceImpl.class);
	private static final int STATE_COMPLETE = 6;
	private static final int STATE_EXPIRE = 7;
	private static final int STATE_BECASHED = 8;
	private static final int STATE_CANCLE = 5;
	private OrdersDao ordersDao;
	@Inject
	private PaySerialService paySerialServiceImpl;
	@Inject
	private EmployeeService employeeServiceImpl;
	@Inject
	private InvestorService investorServiceImpl;
	@Inject
	private ProductService productServiceImpl;
	@Inject
	private EmployeeGroupService employeeGroupServiceImpl;
	@Inject
	private GroupMemberService groupMemberServiceImpl;
	@Inject
	private EmployeeCommissionHistoryService employeeCommissionHistoryServiceImpl;
	@Inject
	private ProductGradeService productGradeServiceImpl;
	@Inject
	private IssuersBackService issuersBackServiceImpl;

	@Override
	@Inject
	public void setBaseDao(BaseDao<Orders, OrdersBean, String> ordersDao) {
		this.baseDao = ordersDao;
		this.ordersDao = (OrdersDao) ordersDao;
	}
	
	
	@Override
	public int sendRevisit(Orders model) {
		try {
			IssuersBack ib = new IssuersBack();
			ib.setId(ObjectId.get().toString());
			ib.setCreateTime(new Date());
			ib.setIssuersId(UserUtils.getIssuersId());
			ib.setOrgId(UserUtils.getIssuersOrgId());
			 
			Orders orders = new Orders();
			orders = ordersDao.get(model.getId());
			ib.setOrderId(orders.getOrderId());
			StringBuilder sb = new StringBuilder();
			Investor investor = investorServiceImpl.get(orders.getInvestorId());
			sb.append("尊敬的"+investor.getName() +"，您好！感谢您信赖、选购"+ orders.getProductName() + 
					"。现根据国家相关规定对您进行购买回访，请如实回答以下两个问题：1，您是否自愿购买"+orders.getProductName()+
					"；2，您是否已知悉"+orders.getProductName()+
					"的相关风险。"); 
			ib.setVisitContent(sb.toString());
			
			int i = issuersBackServiceImpl.save(ib);
			if (i == 1) {
				int j = ordersDao.updateById(model);
				if (1 != j) {
					throw new ServiceException("订单更新失败");
				}
			}
		} catch (ServiceException e) {
			throw new ServiceException("发起回访失败",e);
		}
		return 1;
	}
	
	/**
	 * 获得订单列表
	 * 
	 * @return
	 */
	public List<OrderResBean> getOrderResBeanList(OrderReqBean orderReqBean) {
		String[] list = null;
		List<OrderResBean> resList = new ArrayList<OrderResBean>();
//		List<OrderResBean> resOrderList = new ArrayList<OrderResBean>();
//		List<OrderResBean> resOrderCancleList = new ArrayList<OrderResBean>();
		if (null != orderReqBean.getGroupId() && "" != orderReqBean.getGroupId()) {
			list = orderReqBean.getGroupId().split(",");
			for (String li : list) {
				orderReqBean.setGroupId(li);
				resList.addAll(ordersDao.getOrderResBeanList(orderReqBean));
			}
		} else {
			resList = ordersDao.getOrderResBeanList(orderReqBean);
		}
//		//遍历取消的订单
//		DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//		for (OrderResBean li : resList) {
//			if(li.getState() != STATE_CANCLE){
//				resOrderList.add(li);
//				LOGGER.info(df.format(li.getOrderTime())+"NoCancle");
//			}else{
//				resOrderCancleList.add(li);
//				LOGGER.info(df.format(li.getOrderTime())+"Cancled");
//			}
//		}
//		resOrderList.addAll(resOrderCancleList);
		return resList;
	}

	/**
	 * @param orderReqBean
	 * @return 记录总数
	 */
	public long countByOrgId(OrderReqBean orderReqBean) {
		String[] list = null;
		long sum = 0;
		if (null != orderReqBean.getGroupId() && "" != orderReqBean.getGroupId()) {
			list = orderReqBean.getGroupId().split(",");
			for (String li : list) {
				orderReqBean.setGroupId(li);
				sum += (ordersDao.countByOrgId(orderReqBean));
			}
			return sum;
		} else {
			return ordersDao.countByOrgId(orderReqBean);
		}
	}

	/**
	 * 获取订单详情
	 * 
	 * @param orderId
	 * @return OrderDetialResBean
	 */
	public OrderDetailResBean getOrderDetial(OrderReqBean orderReqBean) {
		return ordersDao.getOrderDetial(orderReqBean);
	}

	/**
	 * 获取订单联系记录
	 * 
	 * @param orderId
	 * @return List<OrderVisitResBean>
	 */
	public List<OrderVisitResBean> getOrderVisitList(OrderResBean orderResBean) {
		return ordersDao.getOrderVisitList(orderResBean);
	}

	/**
	 * @param orderReqBean
	 * @return 联系记录总数
	 */
	public int countVisitNumByOrderId(String id) {
		return ordersDao.countVisitNumByOrderId(id);
	}

	/**
	 * @param id
	 * @return List<OrderPaySerialResBean>
	 */
	public List<OrderPaySerialResBean> getOrderPaySerial(OrderResBean orderResBean) {
		return ordersDao.getOrderPaySerial(orderResBean);
	}

	/**
	 * @param id
	 * @return 支付流水总数
	 */
	public int countPaySerialNumByOrderId(String id) {
		return ordersDao.countPaySerialNumByOrderId(id);
	}

	@Override
	public int complete(Orders orders) {
		try {
			Date date = new Date();
			orders.setState(STATE_COMPLETE);
			orders.setPayTime(date);
			int m = ordersDao.updateById(orders);
			if (0 >= m) {
				LOGGER.error("update orders error");
				throw new ServiceException("update orders error");
			}
			PaySerial paySerial = new PaySerial();
			paySerial.setId(ObjectId.get().toString());
			paySerial.setOrderId(orders.getId());
			paySerial.setPayAmount(orders.getOrderAmount());
			paySerial.setInvestorId(orders.getInvestorId());
			paySerial.setEmployeeId(orders.getEmployeeId());
			paySerial.setPayTime(date);
			paySerial.setState(0);
			paySerial.setPaySerial("T" + (paySerialServiceImpl.count(null) + 1));
			paySerial.setOrgId(orders.getOrgId());
			int l = paySerialServiceImpl.save(paySerial);
			if (0 >= l) {
				LOGGER.error("save paySerial error");
				throw new ServiceException("update paySerial error");
			}
		} catch (Exception e) {
			LOGGER.error("complete order error, msg=[{}].", e.getMessage());
			throw new ServiceException("complete order error", e);
		}
		return 1;
	}

	@Override
	public List<Orders> queryGroupSalesPerformance(GroupOdersReqBean groupOdersReqBean) {
		return ordersDao.queryGroupSalesPerformance(groupOdersReqBean);
	}
	
	@Override
	public List<ProductBreifBean> getOrgProductList(String orgId, String productKey, Integer type) {
		ProductMatchReqBean p = new ProductMatchReqBean();
		p.setOrgId(orgId);
		if(!productKey.equals("TOTAL")){
			p.setProductKey(productKey);
		}
		if(type == 1){
			p.setType(1);
		}
		return ordersDao.getOrgProductList(p);
	}

	@Override
	public List<ProductEmpStatsResBean> getProductEmpStats(ProductEmpStatsReqBean productEmpStatsReqBean) {
		return ordersDao.getProductEmpStats(productEmpStatsReqBean);
	}

//	@Override
//	public long countProductEmpStats(
//			ProductEmpStatsReqBean productEmpStatsReqBean) {
//		return ordersDao.countProductEmpStats(productEmpStatsReqBean);
//	}

	@Override
	public List<ProductRecruitProgressEleBean> getUncompletedProductRecruitProgress(ProductEmpStatsReqBean productEmpStatsReqBean) {
		return ordersDao.getUncompletedProductRecruitProgress(productEmpStatsReqBean);
	}

	public JsonBean addOfflineOrder(OfflineOrderReqBean model, MultipartFile paySignUser,
			MultipartFile idcardFront, MultipartFile idcardBack, MultipartFile bankCard) throws IOException {
		JsonBean json = new JsonBean();
		
		if(StringUtils.isAnyBlank(model.getProductSearch(),model.getInvestorSearch())){
			json.setCode(0);
			json.setMessage("字段不能为空");
			return json;
		}
		
		String idcardFrontFilePath = MyFileUtils.uploadImg(idcardFront,ImgType.OFFLINEORDER);
		String idcardBackFilePath = MyFileUtils.uploadImg(idcardBack,ImgType.OFFLINEORDER);
		String contactFilePath = MyFileUtils.uploadFile(paySignUser,
				MyFileUtils.FILE_TYPE);
		String bankCardFilePath = "";
		
		if(bankCard != null){
			bankCardFilePath = MyFileUtils.uploadImg(bankCard,ImgType.OFFLINEORDER);
		}
		
		Product p = productServiceImpl.get(model.getProductId());
		Employee e = employeeServiceImpl.get(model.getEmployeeId());
		Investor inv = investorServiceImpl.get(model.getInvestorId());
		
		if(p == null){
			json.setCode(0);
			json.setMessage("不存在此产品, 请输入关键字查询并选择，确认无误后再重试！");
			return json;
		}
		if(e == null){
			json.setCode(0);
			json.setMessage("不存在此理财师, 请输入关键字查询并选择，确认无误后再重试！");
			return json;
		}
		if(inv == null){
			json.setCode(0);
			json.setMessage("不存在此投资人, 请输入关键字查询并选择，确认无误后再重试！");
			return json;
		}
		
		if(model.getOrderTime().before(p.getRecruitStartTime()) || 
				model.getPayTime().before(p.getRecruitStartTime()) || 
				model.getPayTime().after(p.getRecruitEndTime()) || 
				model.getOrderTime().after(p.getRecruitEndTime())){
			json.setCode(0);
			json.setMessage("下单时间或者支付时间未在产品募集期限之内");
			return json;
		}
		
		if (-1 == model.getOrderAmout().compareTo(p.getSubStart())) {
			json.setCode(0);
			json.setMessage("认购金额必须大于产品起购金额");
			return json;
		}
		if (model.getGradeId() != null) {
			ProductGrade pg = productGradeServiceImpl.get(model.getGradeId());
			if(-1 == model.getOrderAmout().compareTo(pg.getSubScopeStart()) || 1 == model.getOrderAmout().compareTo(pg.getSubScopeEnd())){
				json.setCode(0);
				json.setMessage("认购金额必须在该收益分档认购范围之内");
				return json;
			}
		}
		
		//减少产品份额
		Double available = BigDecimalUtils.subtract(p.getAvailable(), model.getOrderAmout());
		if(available < 0){
			json.setCode(0);
			json.setMessage("产品份额不足，请联系相应人员！");
			return json;
		}
		p.setAvailable(available);
				
		String orderId = p.getProductCode().toUpperCase() + Ids.get().toString();
		
		Orders order = new Orders();
		order.setEmployeeId(model.getEmployeeId());
		order.setEmployeeName(e.getName());
		order.setProductId(model.getProductId());
		order.setProductName(p.getProductName());
		order.setProductBriefName(p.getBriefName());
		order.setHandlingFee(p.getHandlingFee());
		order.setSubFee(p.getSubFee());
		order.setPayTime(model.getPayTime());
		order.setOrderTime(model.getOrderTime());
		order.setInvestorId(model.getInvestorId());
		order.setBankAccount(model.getBankAccount());
		order.setBankDeposit(model.getBankDeposit());
		order.setBankName(model.getBankName());
		order.setOrderAmount(model.getOrderAmout());
		order.setPaySignUser(contactFilePath);
		order.setIdcardFront(idcardFrontFilePath);
		order.setIdcardBack(idcardBackFilePath);
		if(StringUtils.isNoneEmpty(bankCardFilePath)){
			order.setBankCard(bankCardFilePath);
		}
		order.setOrderAllAmount(BigDecimalUtils.add(
				BigDecimalUtils.add(order.getOrderAmount(), order.getHandlingFee()),
				BigDecimalUtils.multiply(order.getOrderAmount(), order.getSubFee())));
		order.setPaidAmount(order.getOrderAllAmount());
		order.setContactNum(model.getContactNum());
		order.setId(ObjectId.get().toString());
		order.setOrderId(orderId);
		order.setOrgId(UserUtils.getOrgId());
		order.setType(1);
		order.setGradeId(model.getGradeId());
		order.setState(STATE_COMPLETE);
		
		ProductReqBean req = new ProductReqBean();
		req.setProductId(model.getProductId());
		req.setEmployeeId(model.getEmployeeId());
		Product pd = productServiceImpl.getDetail(req);
		
		//查找是否为理财师团队长
		EmployeeGroup eg = new EmployeeGroup();
		eg.setEmployeeId(model.getEmployeeId());
		eg.setDeleted(false);
		EmployeeGroup employeeGroup = employeeGroupServiceImpl.unique(eg);
		
		EmployeeCommissionHistory employeeCommissionHistory = new EmployeeCommissionHistory();
		employeeCommissionHistory.setId(ObjectId.get().toString());
		employeeCommissionHistory.setOrderId(orderId);
		employeeCommissionHistory.setProductId(model.getProductId());
		if(StringUtils.isBlank(pd.getCommissionRate().toString())){
			LOGGER.error("commission rate is none");
			json.setMessage("设置的产品佣金分成有误，请确认后重试");
			json.setCode(0);
            return json;
		}
		employeeCommissionHistory.setCommissionRate(pd.getCommissionRate());
		employeeCommissionHistory.setCommission(BigDecimalUtils.multiply(
				model.getOrderAmout(), pd.getCommissionRate()));
		employeeCommissionHistory.setEmployeeId(model.getEmployeeId());
		employeeCommissionHistory.setCreateTime(new Date());
		
		if (null != employeeGroup && employeeGroup.getPlannerGroup()) {
			if(StringUtils.isBlank(pd.getDividendRate().toString())){
				LOGGER.error("dividend rate is none");
				json.setMessage("设置的产品佣金分成有误，请确认后重试");
				json.setCode(0);
                return json;
			}
			employeeCommissionHistory.setDividendRate(pd.getDividendRate());
			employeeCommissionHistory.setDividend(BigDecimalUtils.multiply(
					model.getOrderAmout(), pd.getDividendRate()));
		} else {
			// 不是团队长，也要插入团队长的提成
			String teamleaderEmId = null;
			try {
				GroupMember gmParam = new GroupMember();
				gmParam.setEmployeeId(model.getEmployeeId());
				String groupId = groupMemberServiceImpl.unique(gmParam).getGroupId();

				teamleaderEmId = employeeGroupServiceImpl.get(groupId)
						.getEmployeeId();
			} catch (Exception e1) {
				LOGGER.error(
						"employee existed multi group error/employee not existed a group error, msg = [{}]",
						e1.getMessage());
			}

			if (null != teamleaderEmId) {
				ProductReqBean productReqBean1 = new ProductReqBean();
				productReqBean1.setProductId(model.getProductId());
				productReqBean1.setEmployeeId(teamleaderEmId);
				Product productDetail1 = productServiceImpl.getDetail(productReqBean1);

				EmployeeCommissionHistory teamleaderECH = new EmployeeCommissionHistory();
				teamleaderECH.setId(ObjectId.get().toString());
				teamleaderECH.setOrderId(orderId);
				teamleaderECH.setProductId(model.getProductId());
				teamleaderECH.setEmployeeId(teamleaderEmId);
				teamleaderECH.setCreateTime(new Date());

				teamleaderECH.setDividendRate(productDetail1.getDividendRate());
				teamleaderECH.setDividend(BigDecimalUtils.multiply(
						model.getOrderAmout(), productDetail1.getDividendRate()));
				teamleaderECH.setState(0);
				employeeCommissionHistoryServiceImpl.save(teamleaderECH);
				LOGGER.info(
						"save employee's teamleader divedend success, teamleaderEmployeeId = [{}]",
						teamleaderEmId);
			}
		}

		employeeCommissionHistory.setState(0);
		employeeCommissionHistoryServiceImpl.save(employeeCommissionHistory);
		LOGGER.info("save employee's commission/devidend success, employeeId = [{}]",
				model.getEmployeeId());
		
		int l = productServiceImpl.updateById(p);
		int result = ordersDao.save(order);
		if(1 == result && 1 == l){
			json.setCode(1);
			json.setMessage("success");
		}else{
			json.setCode(0);
			json.setMessage("save order or update product error, please contact the website manager");
		}
		return json;
	}
	
	/**
	 * 获取机构下所有理财师
	 * 
	 * @param String
	 *            id
	 * @return List<GroupBean>
	 */
	@Override
	public List<EmpBreifBean> getOrgEmployeeList(String tenantIdentifier, String employeeKey) {
		MatchReqBean mBean = new MatchReqBean();
		if (!employeeKey.equals("TOTAL")) {
			mBean.setEmployeeKey(employeeKey);
		}
		mBean.setOrgId(tenantIdentifier);
		List<EmpBreifBean> list = ordersDao.getOrgEmployeeList(mBean);
		return list;
	}

	@Override
	public double saleAmount(IndexStatsReqBean indexStatsReqBean) {
		return ordersDao.saleAmount(indexStatsReqBean);
	}
	
	@Override
	public List<OrderResBean> getAuditOrderList(OrderReqBean orderReqBean){
		return ordersDao.getAuditOrderList(orderReqBean);
	}

	@Override
	public long countAuditOrderByOrgId(OrderReqBean orderReqBean) {
		return ordersDao.countAuditOrderByOrgId(orderReqBean);
	}

	@Override
	public void ordersStateModifyTask() {
		try {
			List<OrderStateResBean> OrderList = getOrderStateList(new Orders());
			if(OrderList.size() == 0){
				return;
			}
			Iterator<OrderStateResBean> iter = OrderList.iterator();
			List<OrderStateResBean> newOrderList = new ArrayList<OrderStateResBean>();
			while (iter.hasNext()) {
				OrderStateResBean o = iter.next();
				DateTime now = new DateTime();
				DateTime setupDate = new DateTime(o.getSetupTime());
				if(setupDate.plusMonths(o.getDuration()).isBefore(now.plusDays(7))){
					o.setState(STATE_EXPIRE);
					newOrderList.add(o);
				}
				if(setupDate.plusMonths(o.getDuration()).isBefore(now)){
					o.setState(STATE_BECASHED);
					newOrderList.add(o);
				}
			}
			int result = 0;
			if(newOrderList.size() != 0){
				result = this.updateOrderListState(newOrderList);
			}
			LOGGER.info("本次定时任务更新订单数量为 = [{}]", result);
		} catch (Exception e) {
			LOGGER.error("Timed Task error, error=[{}]", e.getMessage());
		}
	}

	@Override
	public List<OrderStateResBean> getOrderStateList(Orders o) {
		return ordersDao.getOrderStateList(o);
	}

	@Override
	public Integer updateOrderListState(List<OrderStateResBean> newOrderList) {
		return ordersDao.updateOrderListState(newOrderList);
	}

	@Override
	public List<OfflineApplyResBean> fetchOfflineApplyResBean(String id) {
		return ordersDao.fetchOfflineApplyResBean(id);
	}

	@Override
	public List<OrderOfflineApplyResBean> fetchOrderOfflineApplyResBean(String id) {
		return ordersDao.fetchOrderOfflineApplyResBean(id);
	}

	@Override
	public List<OrderResBean> getRiskResBeanList(OrderReqBean model) {
		return ordersDao.getRiskResBeanList(model);
	}

	@Override
	public long countRiskByOrgId(OrderReqBean model) {
		return ordersDao.countRiskByOrgId(model);
	}

	@Override
	public List<IssuersOrdersResBean> getIssuersOrdersResBeanList(OrderReqBean model) {
		return ordersDao.getIssuersOrdersResBeanList(model);
	}

	@Override
	public long getIssuersOrdersCount(OrderReqBean model) {
		return ordersDao.getIssuersOrdersCount(model);
	}
}
